/box-inline-create {               % => 
  box-generic-inline-create

  dup /Lines [] put
  
  dup box-inline-setup-methods
  dup /box-inline add-type
} def                              % => Box

% Extends the existing line box to include the given child 
% OR starts new line box, if current child is to the left of the box right edge 
% (which should not happen white the line box is filled)
%
% @param $box child box which will be first in this line box
% @param $line_no number of line box
%
/box-inline-extend-line {          % => LineNo Box This
  dup box-inline-get-lines
  length                           % => LineNo Box This NumLines
  3 index le {                     % => LineNo Box This
% New line box started
    2 index
    2 index
    2 index
    box-inline-init-line           % => LineNo Box This
    2 index                        % => LineNo Box This LineNo
  } {                              % => LineNo Box This
    1 index get-left               % => LineNo Box This BoxLeft
    1 index box-inline-get-lines   % => LineNo Box This BoxLeft Lines
    4 index get                    % => LineNo Box This BoxLeft Line
    line-get-right                 % => LineNo Box This BoxLeft LineRight
    lt {                           % => LineNo Box This
      2 index 1 add                % => LineNo Box This LineNo'
      dup
      3 index
      3 index                      % => LineNo Box This LineNo' LineNo' Box This
      box-inline-init-line         % => LineNo Box This LineNo' 
    } {
      dup box-inline-get-lines     % => LineNo Box This Lines
      3 index get                  % => LineNo Box This Line
      2 index exch line-extend     % => LineNo Box This
      2 index                      % => LineNo Box This LineNo
    } ifelse                       % => 
  } ifelse                         % => LineNo Box This LineNo'

  exch pop
  exch pop
  exch pop
} def

/box-inline-get-extra-line-left {  % => This
  dup get-extra-left               % => This EL
  1 index get-parent /null ne {    % => This EL
    1 index get-parent
    /get-extra-line-left
    call-method                    % => This EL ParentEL
    add
  } if

  exch pop
} def

/box-inline-get-extra-line-right {
  dup get-extra-right              % => This EL
  1 index get-parent /null ne {    % => This EL
    1 index get-parent
    /get-extra-line-right
    call-method                    % => This EL ParentEL
    add
  } if

  exch pop
} def

/box-inline-get-lines {
  /Lines get
} def

% Initialize next line box inside this inline 
%
% Adds the next element to _lines array inside the current object and initializes it with the 
% $box parameters
% 
% @param $box child box which will be first in this line box
% @param $line_no number of line box
%
/box-inline-init-line {            % => LineNo Box This
  1 index
  line-create                      % => LinoNo Box This Line

  1 index box-inline-get-lines
  array-prepend
  1 index box-inline-put-lines     % => LineNo Box This
  
  pop pop pop
} def

/box-inline-merge-line {           % => LineNo Box This
  1 index box-inline-get-lines {   % => LineNo Box This Line
    1 index box-inline-get-lines   % => LineNo Box This Line Lines
    array-prepend                  % => LineNo Box This Lines'
    1 index box-inline-put-lines   % => LineNo Box This 
  } forall                         % => LineNo Box This

  exch pop
  exch pop
  box-inline-get-lines length      % => LineNo'
} def

/box-inline-offset {               % => DY DX This
  3 copy
  box-container-offset             % => DY DX This

  dup box-inline-get-lines {       % => DY DX This Line
    3 index exch
    3 index exch
    line-offset                    % => DY DX This
  } forall

  pop pop pop
} def

/box-inline-put-lines {            % => Value This
  exch /Lines exch put
} def

/box-inline-reflow {               % => Context Parent This
% Note that inline boxes (actually SPANS)
% are never added to the parent's line boxes

% Move current box to the parent's current coordinates
% Note that span box will start at the far left of the parent, NOT on its current X!
% Also, note that inline box can have margins, padding and borders!

  1 index get-left
  1 index put-left

  1 index get-top
  1 index get-extra-top sub
  1 index put-top                  % => Context Parent This

% first line of the SPAN will be offset to its parent current-x PLUS the left padding of current span!
  1 index get-current-x
  1 index get-extra-left
  add                              % => Context Parent This CX
  
  dup 3 index put-current-x        % => Context Parent This CX
  1 index put-current-x            % => Context Pareht This 

% Note that the same operation IS NOT applied to parent current-y!
% The padding space is just extended to the top possibly OVERLAPPING the above boxes.

  0 1 index put-width

% Reflow contents

  0                               % => Context Parent This LineNo
  1 index get-content {           % => Context Parent This LineNo Child
% Add current element into _parent_ line box and reflow it
    4 index
    4 index                       % => Context Parent This LineNo Child Context Parent
    2 index
    /reflow call-method           % => Context Parent This LineNo Child
    
% Track the real height of the inline box; it will be used by other functions 
% (say, functions calculating content height)
    dup get-bottom-margin         % => Context Parent This LineNo' Child BM
    3 index
    box-generic-extend-height     % => Context Parent This LineNo Child

    pop
  } forall                        % => Context Parent This LineNo 
  pop                             % => Context Parent This 
    
% Extend parent height to fit this inline box
% TODO: Is it really required? Seems that it will be accomplished by child reflow functions
%  dup get-bottom-margin           % => Context Parent This GBM
%  2 index
%  box-generic-extend-height       % => Context Parent This

% Apply right extra space value (padding + border + margin)
  1 index get-current-x
  1 index get-extra-right
  add
  2 index put-current-x

% After reflow_content we should have the top stack value replace by the value
% of last child bottom collapsed margin

  dup box-container-get-first-data /null ne {
    2 index context-pop-collapsed-margin
    0 3 index context-push-collapsed-margin
  } if

  pop pop pop
} def

/box-inline-reflow-inline {        % => This
  0                                % => This LineNo
  1 index get-content {            % => This LineNo Child
    dup /reflow-inline call-method
      
    dup /box-inline is-a {
      1 index                      % => This LineNo Child LineNo
      1 index                      % => This LineNo Child LineNo Child
      4 index                      % => This LineNo Child LineNo Child This
      box-inline-merge-line        % => This LineNo Child LineNo'

      3 2 roll                     % => This Child LineNo' LineNo
      pop
      exch                         % => This LineNo' Child 
    } {
      1 index                      % => This LineNo Child LineNo
      1 index                      % => This LineNo Child LineNo Child
      4 index                      % => This LineNo Child LineNo Child This
      box-inline-extend-line       % => This LineNo Child LineNo'
      3 2 roll                     % => This Child LineNo' LineNo
      pop
      exch                         % => This LineNo' Child 
    } ifelse                       % => This LineNo' Child

    pop
  } forall

  pop pop
} def

/box-inline-setup-methods {        % => Box
  dup get-box-dict /Methods get    % => Box Methods
  dup /get-extra-line-left  {box-inline-get-extra-line-left} put  
  dup /get-extra-line-right {box-inline-get-extra-line-right} put  
  dup /offset               {box-inline-offset} put  
  dup /reflow               {box-inline-reflow} put
  dup /reflow-inline        {box-inline-reflow-inline} put
  dup /show                 {box-inline-show} put
  pop pop
} def

/box-inline-show {                 % => Viewport This
% Show line boxes background and borders
  dup box-inline-get-lines {       % => Viewport This Line
    1 index 1 index line-fake-box  % => Viewport This Line FakeBox
    
    dup
    4 index                        % => Viewport This Line FakeBox FakeBox Viewport
    4 index get-background
    background-show                % => Viewport This Line FakeBox

    dup
    4 index
    4 index get-border
    border-show                    % => Viewport This Line FakeBox

    pop pop
  } forall

% Show content
  dup get-content {                % => Viewport This Child
    2 index exch
    /show call-method              % => Viewport This
  } forall

  pop pop
} def

/line-create {                     % => Box
  << >>
  dup /right  3 index get-right  put
  dup /left   3 index get-left   put
  dup /top    3 index get-top    put
  dup /bottom 3 index get-bottom put
  exch pop
} def

/line-extend {                     % => Box This
  dup /top get                     % => Box This V1
  2 index get-top                  % => Box This V1 V2
  max
  1 index exch /top exch put
  
  dup /right get                   % => Box This V1
  2 index get-right                % => Box This V1 V2
  max
  1 index exch /right exch put

  dup /bottom get                  % => Box This V1
  2 index get-bottom               % => Box This V1 V2
  min
  1 index exch /bottom exch put

% Left edge of the line box should never be modified

  pop pop
} def

/line-get-right {
  /right get
} def

/line-fake-box {                   % => Box This
% Create the fake box object
  box-block-create                 % => Box This FakeBox
  
% Setup fake box size
  1 index /left get
  1 index put-left

  1 index /right get
  2 index /left get sub
  1 index put-width

  1 index /top get
  1 index get-baseline sub
  1 index put-top

  1 index /top get
  2 index /bottom get sub
  1 index put-height

% Setup padding value
  2 index get-padding
  1 index put-padding

% Setup fake box border and background
  2 index get-background
  1 index put-background

  2 index get-border
  1 index put-border

  exch pop
  exch pop
} def

/line-offset {                     % => DY DX This
  dup /top get                     % => DY DX This Top
  3 index add                      % => DY DX This Top'
  1 index exch                     % => DY DX This This Top' 
  /top exch put                    % => DY DX This 

  dup /bottom get                  % => DY DX This Bottom
  3 index add                      % => DY DX This Bottom'
  1 index exch                     % => DY DX This This Bottom' 
  /bottom exch put                 % => DY DX This 

  dup /left get                    % => DY DX This Left
  2 index add                      % => DY DX This Left'
  1 index exch                     % => DY DX This This Left' 
  /left exch put                   % => DY DX This 

  dup /right get                   % => DY DX This Right
  2 index add                      % => DY DX This Right'
  1 index exch                     % => DY DX This This Right' 
  /right exch put                  % => DY DX This

  pop pop pop
} def